﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Runtime.Serialization;
using Faust.Andrew.MTG.Utilities;

namespace Faust.Andrew.MTG
{
    [DataContract]
    public class Deck : INotifyPropertyChanged
    {        
        [DataMember]
        public ObservableCollection<DeckCard> Cards { get; private set; }

        public bool IsChanged { get; set; }

        public int DeckID { get; set; }
        private string _name;

        private bool _isConstructed;
        [DataMember]
        public bool IsConstructed
        {
            get { return _isConstructed; }
            set
            {
                if (_isConstructed != value)
                {
                    _isConstructed = value;
                    FirePropertyChangedEvent("IsConstructed");
                }
            }
        }
        

        [DataMember]
        public string Name
        {
            get
            {
                return _name;
            }
            set
            {
                if (_name != value)
                {
                    _name = value;
                    FirePropertyChangedEvent("Name");
                }
            }
        }
        private string _description;       
        public string Description
        {
            get
            {
                return _description;
            }
            set
            {
                if (_description != value)
                {
                    _description = value;
                    FirePropertyChangedEvent("Description");
                }
            }
        }

        public Deck()
        {
            Cards = new ObservableCollection<DeckCard>();
            
        }

        public void SetCardQuantity(Card card, int quantity, bool adjustment)
        {
            if (card == null)
            {
                throw new ArgumentNullException("card", "card is null.");
            }

            //If the card exists, but quantity is < 1 we remove the card from the deck
            //If the card exists and quantity is > 0 we change the quantity
            //If the card doesn't exists and the quantity is > 0 we add the card

            DeckCard deckCard = Cards.SingleOrDefault(tempCard => card.Equals(tempCard));

            bool wasChanged = false;
            
            if (deckCard != null && quantity < 1)
            {
                wasChanged = true;

                //if adjustment is true we want to decrease the number of cards in the deck. If adjustment is false, we want to remove the card
                if (adjustment)
                {
                    //Remember the quantity is possibly a negative number. If we subtract we'll just be cancelling it out and adding cards.
                    deckCard.Quantity += quantity;
                }
                else
                {
                    Cards.Remove(deckCard);
                }
            }
            else if (deckCard != null && quantity > 0)
            {
                wasChanged = true;

                //if Adjustment is true we want to add the quantity to the existing quantity. Otherwise we overwrite the quantity
                if (adjustment)
                {
                    deckCard.Quantity += quantity;
                }
                else
                {
                    deckCard.Quantity = quantity;
                }
            }
            else if ((deckCard == null)&& quantity > 0)
            {
                wasChanged = true;

                deckCard = new DeckCard();
                deckCard.Card = card;
                deckCard.Quantity = quantity;

                deckCard.PropertyChanged += new PropertyChangedEventHandler(deckCard_PropertyChanged);

                Cards.Add(deckCard);                
            }

            if (wasChanged)
            {
                FirePropertyChangedEvent("Cards");
            }
        }

        void deckCard_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "Quantity")
            {
                DeckCard card = (DeckCard)sender;
                if (card.Quantity == 0)
                {
                    Cards.Remove(card);
                }
            }

            FirePropertyChangedEvent("Cards");
        }

        public void SetCardQuantity(string multiverseID, int quantity, bool adjustment)
        {
            if (String.IsNullOrEmpty(multiverseID))
            {
                throw new ArgumentException("multiverseID is null or empty.", "multiverseID");
            }

            Card card = new Card();
            card.MultiverseID = multiverseID;

            SetCardQuantity(card, quantity, adjustment);
        }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;


        protected void FirePropertyChangedEvent(string propertyName)
        {
            IsChanged = true;
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        #endregion
    }
}
